﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace FS_2013_GUI
{
    public class Connection
    {
        public string receivedPath;
        public bool ready;

        private TcpClient client;
        private int port;
        private bool stop;
        private Thread receive;
        private Socket clientSock;
        private byte[] clientData;

        public Connection()
        {
            ready = false;
            receivedPath = @"C:\Users\Michael13\Desktop\Receive\";
            port = 1;
            clientData = new byte[1024 * 3];
            stop = false;
        }

        public void Start()
        {
            Connect();
        }

        private void Connect()
        {
            receive = new Thread(Receive);
            stop = false;
            client = new TcpClient();
            while (!client.Connected)
            {
                try
                {
                    client.Connect(IPAddress.Parse("127.0.0.1"), port); //178.137.199.13
                }
                catch { }
            }
            receive.Start();
        }

        public void Disconnect()
        {
            ready = false;
            stop = true;
            if (client != null)
                client.Close();
        }

        public void Reconnect()
        {
            Disconnect();
            Thread.Sleep(1000);
            Connect();
        }

        public void Send(string message)
        {
            if (client.Connected)
            {
                NetworkStream ns = client.GetStream();
                if (ns != null)
                {
                    byte[] buffer = Encoding.Default.GetBytes(message);
                    ns.Write(buffer, 0, buffer.Length);
                }
            }
        }

        public void Receive()
        {
            string request = "";
            while (!stop)
            {
                try
                {
                    if (client.Connected)
                    {
                        NetworkStream ns = client.GetStream();
                        while (ns.DataAvailable)
                        {
                            byte[] buffer = new byte[client.Available];
                            ns.Read(buffer, 0, buffer.Length);
                            request += Encoding.Default.GetString(buffer);
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                if (request != "")
                {
                    ExecuteRequest(request);
                    request = "";
                }
                Thread.Sleep(100);
            }
        }

        private void ConnectFiles()
        {
            IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port + 1); //178.137.199.13
            clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            while (!clientSock.Connected)
                try
                {
                    clientSock.Connect(ipEnd);
                }
                catch { }
        }

        public void StarteceiveFiles(int numberOfFiles)
        {
            Thread rf = new Thread(ReceiveFiles);
            rf.Start(numberOfFiles);
        } 

        public void ReceiveFiles(object data)
        {
            int number = (int)data;
            for (int i = 0; i < number; i++)
            {
                int receivedBytesLen = 0;
                int fileNameLen = -1;
                string fileName = null;

                ConnectFiles();

                while (clientSock.Available == 0)
                { }
                while ((receivedBytesLen = clientSock.Receive(clientData, clientData.Length, 0)) != 0)
                {
                    BinaryWriter bWrite;
                    if (fileName == null && fileNameLen == -1)
                    {
                        fileNameLen = BitConverter.ToInt32(clientData, 0);
                        fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
                        if (File.Exists(receivedPath + fileName))
                        {
                            File.Delete(receivedPath + fileName);
                        }
                        bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append)); ;
                        bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
                        bWrite.Close();
                        continue;
                    }

                    bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append));
                    bWrite.Write(clientData, 0, receivedBytesLen);
                    bWrite.Close();
                }
                MessageBox.Show("File received: "+fileName);
                clientSock.Close();
                clientSock = null;
            }
        }

        private void ExecuteRequest(string request)
        {
            string[] task = request.Split(' ');
            if (task[0] == "reconnect")
            {
                port = Int32.Parse(task[1]);
                Reconnect();
                ready = true;
                return;
            }
            if (task[0] == "login")
            {
                if (task[1] == "true")
                {
                    Global.authorizedUser = true;
                    if (task[2] == "true")
                        Global.admin = true;
                    else
                        Global.admin = false;
                }
                else
                    Global.authorizedUser = false;
                MainWindow.ev.Set();
                return;
            }
            if (task[0]== "get_file_list")
            {
                DownloadWindow.fileNames = request;
                return;
            }
        }
    }
}
